package org.duiduo.aspect;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 拦截对这个包下所有方法的访问 的切面
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Pointcut("execution(* org.duiduo.controller.*.*(..))")
    public void loginLog() {
    }

    // 前置通知
    @Before("loginLog()")
    public void loginBefore(JoinPoint joinPoint) {
        // 我们从请求的上下文中获取request，记录请求的内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        log.info("请求路径:{}", request.getRequestURL());
        log.info("请求方式:{}", request.getMethod());
        log.info("方法名:{}", joinPoint.getSignature().getName());
        log.info("类路径:{}", joinPoint.getSignature().getDeclaringTypeName());
        log.info("参数:{}", Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "object", pointcut = "loginLog()")
    public void doAfterReturning(Object object) {
        log.info("方法的返回值:{}", object);
    }

    // 方法发生异常时执行该方法
    @AfterThrowing(throwing = "e", pointcut = "loginLog()")
    public void throwsExecute(JoinPoint joinPoint, Exception e) {
        log.error("方法执行异常:", e);
    }

    // 后置通知
    @After("loginLog()")
    public void afterInform() {
        log.info("后置通知结束");
    }

    // 环绕通知
    @Around("loginLog()")
    public Object surroundInform(ProceedingJoinPoint proceedingJoinPoint) {
        log.info("环绕通知开始...");
        try {
            Object o = proceedingJoinPoint.proceed();
            log.info("方法环绕proceed，结果是:{}", o);
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}
